package com.condroid;

//import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

import ioio.lib.api.Uart;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;

/**
 * the main Activity of the application.
 * Refer to "Write a Console App on Android using Java" by Chilap 
 * http://www.codeproject.com/KB/android/cmdconsole.aspx
 * @author JUN GAO
 * Condroid Summer CSD 2011 - KTH
 */
public class MainActivity extends Activity {
	private Button settingsButton, shtcutButton, stdbyButton, aboutButton,
			enterButton;
	private EditText in;
	private ConsoleView consoleView;
	private ConsoleOutputView outputView;
	private IOIOThread ioioThread;
	private static UartInfo uartInfo = null;
	private static Uart uart = null;
	private static OutputStream outStream = null;
	private static InUartThread inUartThread = null;
	private CmdCmit cmdCmit;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		ConstantData.mainActivity = this;
		setUpViews();
		setUpIOIO();
		getPhoneInfo();
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			new AlertDialog.Builder(this).setIcon(R.drawable.test5)
					.setTitle("ConDroid: easy way to control!")
					.setMessage("Quit ConDroid?")
					.setPositiveButton("Yes", dialogButtonListener)
					.setNegativeButton("No", null).show();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
//		if (inUartThread != null) {
//			inUartThread.finish();
//			try {
//				inUartThread.join();
//			} catch (InterruptedException ie) {
//				// TODO Auto-generated catch block
//				Log.d("ConDroid", "inUartThread join error", ie);
//			}
//			inUartThread = null;
//		}
//
//		if (uart != null) { // && uartInfo != null) {
//			ioioThread.closeUart(uart, uartInfo);
//			uart = null;
//		}
//
//		
//		IOIOThread.abort();
//		try {
//			ioioThread.join();
//			Log.d("ConDroid", "ioioThread join");
//		} catch (InterruptedException e) { 
//			// TODO Auto-generated catch block
//			Log.e("ConDroid", "ioioThread join error", e);
//		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (ConstantData.smsReceiver != null){
			getApplicationContext().unregisterReceiver(ConstantData.smsReceiver);
			ConstantData.smsReceiver = null;
		}
		if (ConstantData.smsDealer != null){
			ConstantData.smsDealer.finish();
			ConstantData.smsDealer = null;
		}
	}

	private void setUpViews() {
		settingsButton = (Button) findViewById(R.id.main_settings);
		shtcutButton = (Button) findViewById(R.id.main_shtcut);
		stdbyButton = (Button) findViewById(R.id.main_stdby);
		aboutButton = (Button) findViewById(R.id.main_about);
		enterButton = (Button) findViewById(R.id.main_enter);
		in = (EditText) findViewById(R.id.main_inputBox);

		// init display text views
		Display display = this.getWindowManager().getDefaultDisplay();
		DisplayMetrics metrics = new DisplayMetrics();
		display.getMetrics(metrics);

		LinearLayout ll = (LinearLayout) findViewById(R.id.main_consoleLayerout);
		outputView = new ConsoleOutputView(this, metrics.heightPixels);
		ll.addView(outputView);
		outputView.setFontSize(FONT_SIZE);

		consoleView = (ConsoleView) findViewById(R.id.main_consoleScroll);
		consoleView.setScrollViewListener(outputView);

		settingsButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(MainActivity.this,
						SettingsActivity.class);
				startActivity(intent);
			}
		});

		shtcutButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(MainActivity.this,
						ShtcutActivity.class);
				startActivity(intent);
			}
		});

		stdbyButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(MainActivity.this,
						StdbyActivity.class);
				startActivity(intent);
			}
		});

		aboutButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(MainActivity.this,
						AboutActivity.class);
				startActivity(intent);
			}
		});

		enterButton.setOnClickListener(enterListener);

		in.setOnKeyListener(keyListener);

	}

	private DialogInterface.OnClickListener dialogButtonListener = new DialogInterface.OnClickListener() {

		@Override
		public void onClick(DialogInterface dialog, int which) {
			// TODO Auto-generated method stub
			finish();
			System.runFinalizersOnExit(true);
			System.exit(0);
		}
	};

	private EditText.OnKeyListener keyListener = new EditText.OnKeyListener() {

		@Override
		public boolean onKey(View v, int keyCode, KeyEvent event) {
			// TODO Auto-generated method stub
			if (keyCode == KeyEvent.KEYCODE_ENTER
					&& event.getAction() == KeyEvent.ACTION_UP) {
				if (setupUart())
					issueCommand();
				return true;
			}
			return false;
		}
	};

	private View.OnClickListener enterListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			if (setupUart());
				issueCommand();
		}
	};

	private boolean setupUart() {
		if (!ioioThread.isConnected()) {
			Toast.makeText(getApplicationContext(),
					"IOIO connection has not been setup! Try later!",
					Toast.LENGTH_SHORT).show();
			return false;
		}
		if (uart == null) {
			Settings.getConfiguration(this);
			int rxPin = Settings.getRcvPort();
			int txPin = Settings.getTransPort();
			int baud = Settings.getbaud();
			Uart.Parity parity = Settings.getparity();
			Uart.StopBits stopBits = Settings.getstopBits();

			if (rxPin == 0 || txPin == 0 || baud == 0 || parity == null
					|| stopBits == null) {
				Toast.makeText(getApplicationContext(),
						"Set the correct connection parameter first!",
						Toast.LENGTH_SHORT).show();
				return false;
			} else
				uartInfo = new UartInfo(rxPin, txPin, baud, parity, stopBits);

			if (!ioioThread.openUart(uartInfo)) {
				Toast.makeText(getApplicationContext(),
						"Uart info has problem!", Toast.LENGTH_SHORT).show();
				return false;
			} else {
				uart = ioioThread.getUart();
//				int counter;
//				for (counter = 0; (uart = ioioThread.getUart()) == null
//						|| counter < 3; counter++) {
//					try {
//						Thread.sleep(250);
//					} catch (InterruptedException e) {
//						// TODO Auto-generated catch block
//						e.printStackTrace();
//					}
//				}
				if (uart == null) {
					Toast.makeText(getApplicationContext(),
							"Can not set up Uart!", Toast.LENGTH_SHORT).show();
					return false;
				}
				inUartThread = new InUartThread(uart.getInputStream(), uiHandler, ConstantData.ControlType.CONSOLE);
				inUartThread.start();
				outStream = uart.getOutputStream();
				
				Toast.makeText(getApplicationContext(), uartInfo.toString(), Toast.LENGTH_SHORT).show();
				ConstantData.consoleUartInfo = uartInfo;
				ConstantData.consoleUart = uart;
				ConstantData.consoleInUartThread = inUartThread;
				ConstantData.consoleOutStream = outStream;

				if (cmdCmit == null)
					cmdCmit = new CmdCmit(outStream);
				else
					cmdCmit.setOutStream(outStream);
			}
		}
		return true;
	}

	private void issueCommand() {
		String s = in.getText().toString().trim();

		try {
			if (cmdCmit.setCmd(s)) {
				cmdCmit.exeCmd();
				//write(s);
			} else {
				writeln("command incorrect!");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			writeln("exeCmd IOException!");
		} catch (InterruptedException ie) {
			writeln("exeCmd InterruptedException!");
		}
		in.setText("");
	}

	private void write(String msg) {
		outputView.appendText(msg);
		consoleView.post(scrollToBottomAction);
	}

	private void writeln(String msg) {
		outputView.appendText(msg);
		outputView.appendText(ConstantData.NEWLINE);
		consoleView.post(scrollToBottomAction);

	}

	private Runnable scrollToBottomAction = new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			if (outputView.getViewableHeight() > consoleView.getHeight()) {
				consoleView.scrollTo(0, outputView.getHeight());
			}
		}

	};

	private void setUpIOIO() {
		ioioThread = IOIOThread.getInstance();
		if (!ioioThread.isAlive())
			ioioThread.start();
		ioioThread.setErrorReportHandler(uiHandler);// for debugging to display
													// ioioThread errors.
	}

	private void getPhoneInfo() {
		TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		ConstantData.phoneNo = tm.getLine1Number();
		ConstantData.appContext = getApplicationContext();
	}

	private Handler uiHandler = new Handler() {
		@Override
		public void handleMessage(Message m) {
			String s = (String) m.obj;
			write(s);
		}
	};

	private final int FONT_SIZE = 12;
}
